<!DOCTYPE html>

<html>
<head>
  <title>parser.js</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
      <ul id="jump_to">
        <li>
          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
          <a class="small" href="javascript:void(0);">+</a>
          <div id="jump_wrapper">
          <div id="jump_page">
            
              
              <a class="source" href="browser.html">
                browser.js
              </a>
            
              
              <a class="source" href="functions.html">
                functions.js
              </a>
            
              
              <a class="source" href="index.html">
                index.js
              </a>
            
              
              <a class="source" href="parser.html">
                parser.js
              </a>
            
              
              <a class="source" href="symtab.html">
                symtab.js
              </a>
            
              
              <a class="source" href="tokenizer.html">
                tokenizer.js
              </a>
            
              
              <a class="source" href="walker.html">
                walker.js
              </a>
            
          </div>
        </li>
      </ul>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>parser.js</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre><span class="comment">/**
 * http://dev.w3.org/csswg/css-syntax/#parsing   准绳
 * 组合media query  有时候设错的条件 导致重复
 * TODO: roole 的占位
 * TODO: 完成 block componentValue 等的重构
 * TODO: animate 直接接 keyframes
 * TODO: parser还是要尽量改写ast
 * TODO: forEach 性能爆差 全部改回来
 */</span>

<span class="keyword">var</span> tk = require(<span class="string">'./tokenizer'</span>),
    tree = require(<span class="string">'./node/index'</span>),
    functions = require(<span class="string">'./functions'</span>),
    Color = require(<span class="string">'./helper/color'</span>),
    _ = require(<span class="string">'./helper/util'</span>),
    symtab = require(<span class="string">'./symtab'</span>),
    perror = <span class="keyword">new</span> Error(),
    test_t,
    slice = [].slice;


<span class="keyword">var</span> combos = [<span class="string">'WS'</span>, <span class="string">'&gt;'</span>, <span class="string">'~'</span>, <span class="string">'+'</span>];
<span class="keyword">var</span> skipStart = <span class="string">'WS NEWLINE COMMENT ;'</span>; 
<span class="keyword">var</span> operators = <span class="string">'+ - * /'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>判断</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="keyword">var</span> isSkipStart = _.makePredicate(skipStart);
<span class="keyword">var</span> isCombo = _.makePredicate(combos);
<span class="keyword">var</span> isSelectorSep = _.makePredicate(combos.concat([<span class="string">'PSEUDO_CLASS'</span>, <span class="string">'PSEUDO_ELEMENT'</span>, <span class="string">'ATTRIBUTE'</span>, <span class="string">'CLASS'</span>, <span class="string">'HASH'</span>,<span class="string">'&amp;'</span>, <span class="string">'IDENT'</span>, <span class="string">'*'</span>]));
<span class="keyword">var</span> isOperator = _.makePredicate(operators);
<span class="keyword">var</span> isColor = _.makePredicate(<span class="string">"aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgrey darkgreen darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray grey green greenyellow honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgrey lightgreen lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen"</span>)
<span class="keyword">var</span> isMcssAtKeyword = _.makePredicate(<span class="string">'mixin extend var'</span>);
<span class="keyword">var</span> isMcssFutureAtKeyword = _.makePredicate(<span class="string">'if else css for'</span>);
<span class="keyword">var</span> isCssAtKeyword = _.makePredicate(<span class="string">'import page keyframe media font-face charset'</span>);
<span class="keyword">var</span> isShorthandProp = _.makePredicate(<span class="string">'background font margin border border-top border-right border-bottom border-left border-width border-color border-style transition padding list-style border-radius.'</span>)

<span class="keyword">var</span> isWSOrNewLine = _.makePredicate(<span class="string">'WS NEWLINE'</span>);
<span class="keyword">var</span> isCommaOrParen = _.makePredicate(<span class="string">', )'</span>);

<span class="keyword">var</span> mayNotPsedudoClass = <span class="regexp">/^:-?[_A-Za-z][-_\w]*$/</span>;



<span class="keyword">var</span> isBuildInFunction = <span class="keyword">function</span>(name){
    <span class="keyword">return</span> !!biFunctions[name];
}



<span class="function"><span class="keyword">function</span> <span class="title">Parser</span><span class="params">(input, options)</span>{</span>
    <span class="keyword">if</span>(input) <span class="keyword">this</span>.setInput(input, options);
}</pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>yy.Parser = Parser</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>exports.Parser = Parser
exports.parse = <span class="keyword">function</span>(input, options){
    <span class="keyword">var</span> parser = <span class="keyword">new</span> Parser(input, options);
    <span class="keyword">return</span> parser.parse();
}

Parser.prototype = {</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>===============</p>

            </div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap for-h1">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <h1>main </h1>

            </div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    parse: <span class="keyword">function</span>(input, options){</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <p>this.setInput(input, options)</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">return</span> <span class="keyword">this</span>.stylesheet();        
    },
    setInput: <span class="keyword">function</span>(input, options){
        <span class="keyword">this</span>.options = options || {};
        <span class="keyword">this</span>.tokenizer = tk(input, _.extend(options||{}, {ignoreComment:<span class="literal">true</span>}));
        <span class="keyword">this</span>.lookahead = <span class="keyword">this</span>.tokenizer.pump();</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>Temporarily ll(3) parser
lookahead number = 3;
this.lookahead = [this.tokenizer.lex(), this.tokenizer.lex(), this.tokenizer.lex()];</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">this</span>.p = <span class="number">0</span>;
        <span class="keyword">this</span>.length = <span class="keyword">this</span>.lookahead.length;
        <span class="keyword">this</span>.states = [<span class="string">'accept'</span>];
        <span class="keyword">this</span>.state=<span class="string">'accept'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>symbol table</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">this</span>.scope = <span class="keyword">this</span>.options.scope || <span class="keyword">new</span> symtab.Scope();
        <span class="keyword">this</span>.rulesets = [];

        <span class="keyword">this</span>.marked = <span class="literal">null</span>;
        <span class="keyword">return</span> <span class="keyword">this</span>;
    },

    next: <span class="keyword">function</span>(k){
        k = k || <span class="number">1</span>;
        <span class="keyword">this</span>.p += k;</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>@TODO 以后再修改为token流
var cur = this.p,
    marked = this.marked;
this.p += k;//游标
// var offset = k - 3;
// if(offset &gt; 0){ //如果超过了一轮
//     while(offset--) this.tokenizer.lex();// discard这部分已经路过的token
// }else{
for(var i = 0; i &lt; k ; i++){
    var lex = marked === null &amp;&amp; this.markstack.length? this.markstack.shift(): this.tokenizer.lex(); 
    this.lookahead[(cur + i /<em> + 3</em>/ ) % 3] = lex;
    if(marked !== null){
        this.markstack.push(lex);
    }
}
// }
this.skip(&#39;COMMENT&#39;);</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    },</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <p>next: function(k){
    k = k || 1;
    //@TODO 以后再修改为token流
    // var cur = this.p,
    //     marked = this.marked;
    // this.p += k;//游标
    // // var offset = k - 3;
    // // if(offset &gt; 0){ //如果超过了一轮
    // //     while(offset--) this.tokenizer.lex();// discard这部分已经路过的token
    // // }else{
    // for(var i = 0; i &lt; k ; i++){
    //     var lex = marked === null &amp;&amp; this.markstack.length? this.markstack.shift(): this.tokenizer.lex(); 
    //     this.lookahead[(cur + i /<em> + 3</em>/ ) % 3] = lex;
    //     if(marked !== null){
    //         this.markstack.push(lex);
    //     }
    // }
    // // }
},</p>
<pre><code> _</code></pre>
<hr>

            </div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    pushState:<span class="keyword">function</span>(condition){
        <span class="keyword">this</span>.states.push(condition);
        <span class="keyword">this</span>.state = condition;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <p>TODO:</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    popState:<span class="keyword">function</span>(){
        <span class="keyword">this</span>.states.pop();
        <span class="keyword">this</span>.state = <span class="keyword">this</span>.states[<span class="keyword">this</span>.states.length-<span class="number">1</span>];
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-14">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-14">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    match: <span class="keyword">function</span>(tokenType, val){
        <span class="keyword">if</span>(!<span class="keyword">this</span>.eat(tokenType, val)){
            <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll();</pre></div></div>
            
        </li>
        
        
        <li id="section-15">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-15">&#182;</a>
              </div>
              <p>_.log(this.lookahead, this.ll(2));</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            <span class="keyword">this</span>.error(<span class="string">'expect:"'</span> + tokenType + <span class="string">'" -&gt; got: "'</span> + ll.type + (ll.val? String(ll.val): <span class="string">''</span>)+ <span class="string">'"'</span>);
        }
    },
    expect: <span class="keyword">function</span>(tokenType, val){

    },
    matcheNewLineOrSemeColon: <span class="keyword">function</span>(){
        <span class="keyword">if</span>(<span class="keyword">this</span>.eat(<span class="string">';'</span>)){
            <span class="keyword">return</span> <span class="literal">true</span>;
        }<span class="keyword">else</span> <span class="keyword">if</span>(<span class="keyword">this</span>.eat(<span class="string">'NEWLINE'</span>)){
            <span class="keyword">return</span> <span class="literal">true</span>;
        }<span class="keyword">else</span>{
            <span class="keyword">this</span>.error(<span class="string">'expect: "NEWLINE" or ";"'</span>+ <span class="string">'-&gt;got: '</span> + <span class="keyword">this</span>.ll().type);
        }
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-16">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-16">&#182;</a>
              </div>
              <p>Temporarily set to ll(3) parser,</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    ll: <span class="keyword">function</span>(k){
        k = k || <span class="number">1</span>;
        <span class="keyword">if</span>((<span class="keyword">this</span>.p + k) &gt; <span class="keyword">this</span>.length){
            <span class="keyword">return</span> <span class="keyword">this</span>.lookahead[<span class="keyword">this</span>.length-<span class="number">1</span>];
        }
        <span class="keyword">return</span> <span class="keyword">this</span>.lookahead[<span class="keyword">this</span>.p + k -<span class="number">1</span>];</pre></div></div>
            
        </li>
        
        
        <li id="section-17">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-17">&#182;</a>
              </div>
              <p>return this.lookahead[(this.p + k - 1) % 3];</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    },</pre></div></div>
            
        </li>
        
        
        <li id="section-18">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-18">&#182;</a>
              </div>
              <p>lookahead</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    la: <span class="keyword">function</span>(k){
        <span class="keyword">return</span> <span class="keyword">this</span>.ll(k).type;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-19">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-19">&#182;</a>
              </div>
              <p>type at pos is some type</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    is: <span class="keyword">function</span>(pos, tokenType){
        <span class="keyword">return</span> <span class="keyword">this</span>.la(pos) === tokenType;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-20">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-20">&#182;</a>
              </div>
              <p>简单版本 只允许mark一次</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    mark: <span class="keyword">function</span>(){
        <span class="keyword">this</span>.marked = <span class="keyword">this</span>.p;
    },
    restore: <span class="keyword">function</span>(){
        <span class="keyword">if</span>(<span class="keyword">this</span>.marked != <span class="literal">undefined</span>) <span class="keyword">this</span>.p = <span class="keyword">this</span>.marked;
        <span class="keyword">this</span>.marked = <span class="literal">null</span>;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-21">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-21">&#182;</a>
              </div>
              <p>expect
some times we need to ignored some lookahead , etc. NEWLINE</p>
<p>while to eat &#39;;&#39;
1. eat ;
2. eat newLine;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    eat: <span class="keyword">function</span>(tokenType){
        <span class="keyword">if</span>(<span class="keyword">this</span>.la() === tokenType){
            <span class="keyword">this</span>.next();
            <span class="keyword">return</span> <span class="literal">true</span>;
        }
    },
    skip: <span class="keyword">function</span>(type){
        <span class="keyword">var</span> skiped, la, test;
        <span class="keyword">while</span>(<span class="literal">true</span>){
            la = <span class="keyword">this</span>.la();
            test = <span class="keyword">typeof</span> type ===<span class="string">'string'</span>? 
                type === la: type(la);
            <span class="keyword">if</span>(test){
                <span class="keyword">this</span>.next();
                skiped = <span class="literal">true</span>;
            }
            <span class="keyword">else</span> <span class="keyword">break</span>;    
        }
        <span class="keyword">return</span> skiped;
    },
    skipStart: <span class="keyword">function</span>(){
        <span class="keyword">return</span> <span class="keyword">this</span>.skip(isSkipStart);
    },
    skipWSorNewlne: <span class="keyword">function</span>(){
        <span class="keyword">return</span> <span class="keyword">this</span>.skip(isWSOrNewLine);
    },
    error: <span class="keyword">function</span>(msg){
        console.log(<span class="keyword">this</span>.stylesheet,<span class="keyword">this</span>.ll(-<span class="number">3</span>), <span class="keyword">this</span>.ll(-<span class="number">1</span>), <span class="keyword">this</span>.ll(<span class="number">1</span>),<span class="keyword">this</span>.ll(<span class="number">2</span>))
        <span class="keyword">throw</span> Error(msg + <span class="string">" on line:"</span> + <span class="keyword">this</span>.ll().lineno);
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-22">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-22">&#182;</a>
              </div>
              <h2>scope man</h2>

            </div>
            
        </li>
        
        
        <li id="section-23">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-23">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    down: <span class="keyword">function</span>(ruleset){
        <span class="keyword">if</span>(ruleset) <span class="keyword">this</span>.rulesets.push(ruleset);
        <span class="keyword">this</span>.scope = <span class="keyword">new</span> symtab.Scope(<span class="keyword">this</span>.scope);
    },
    up: <span class="keyword">function</span>(ruleset){
        <span class="keyword">if</span>(ruleset) <span class="keyword">this</span>.rulesets.pop();
        <span class="keyword">this</span>.scope = <span class="keyword">this</span>.scope.getOuterScope();
    },
    concatSelector: <span class="keyword">function</span>(selectorList){
        <span class="keyword">var</span> ss = <span class="keyword">this</span>.rulesets;
        <span class="keyword">if</span>(!ss.length) <span class="keyword">return</span> selectorList;

        <span class="keyword">var</span> parentList = ss[ss.length - <span class="number">1</span>].selector,
            slist = selectorList.list,
            plist = parentList.list,
            slen = slist.length, 
            plen = plist.length,
            sstring, pstring, rstring,
            s, p, res;
        <span class="keyword">var</span> res = <span class="keyword">new</span> tree.SelectorList();
        <span class="keyword">for</span>(p = <span class="number">0</span>; p &lt; plen; p ++){
            pstring = plist[p].string;
            <span class="keyword">for</span>(s = <span class="number">0</span>; s &lt; slen; s ++) {
                sstring = slist[s].string;
                <span class="keyword">if</span>(~sstring.indexOf(<span class="string">'&amp;'</span>)){
                    rstring = sstring.replace(<span class="regexp">/&amp;/g</span>, pstring)
                }<span class="keyword">else</span>{
                    rstring = pstring + <span class="string">' '</span> + sstring;
                }
                res.list.push(<span class="keyword">new</span> tree.ComplexSelector(rstring));
            }
        }
        <span class="keyword">return</span> res
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-24">
            <div class="annotation">
              
              <div class="pilwrap for-h1">
                <a class="pilcrow" href="#section-24">&#182;</a>
              </div>
              <h1>parse Function</h1>

            </div>
            
        </li>
        
        
        <li id="section-25">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-25">&#182;</a>
              </div>
              <p>1.main</p>
<p>stylesheet(topLevel)
 : WS      {skipWhiteSpace}
 | stmt EOF
 | 
 ;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    stylesheet: <span class="keyword">function</span>(){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.Stylesheet();
        <span class="keyword">this</span>.stylesheet = node;
        <span class="keyword">while</span>(<span class="keyword">this</span>.la(<span class="number">1</span>) !== <span class="string">'EOF'</span>){
            <span class="keyword">this</span>.skipStart();
            <span class="keyword">var</span> stmt = <span class="keyword">this</span>.stmt();
            node.list.push(stmt)
            <span class="keyword">this</span>.skipStart();
        }
        <span class="keyword">return</span> node;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-26">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-26">&#182;</a>
              </div>
              <p>statement
stmt
 : ruleset
 | atrule
 ;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    stmt: <span class="keyword">function</span>(){
        <span class="keyword">var</span> tokenType = <span class="keyword">this</span>.la(<span class="number">1</span>);
        <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll(),
            ll2 = <span class="keyword">this</span>.ll(<span class="number">2</span>),
            la = ll.type,
            la2 = ll2.type;
        <span class="keyword">if</span>(la === <span class="string">'AT_KEYWORD'</span>){
            <span class="keyword">return</span> <span class="keyword">this</span>.atrule();
        }
        <span class="keyword">if</span>(la === <span class="string">'IDENT'</span>){
            <span class="keyword">var</span> start = ll.val.charAt(<span class="number">0</span>);
            <span class="keyword">if</span>(start === <span class="string">'$'</span>) <span class="keyword">return</span> <span class="keyword">this</span>.<span class="keyword">var</span>(<span class="literal">true</span>);
        }

        <span class="keyword">if</span>(isSelectorSep(la)){
            <span class="keyword">return</span> <span class="keyword">this</span>.ruleset(<span class="literal">true</span>);
        }
        <span class="keyword">this</span>.error(<span class="string">'invliad statementstart'</span>);
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-27">
            <div class="annotation">
              
              <div class="pilwrap for-h1">
                <a class="pilcrow" href="#section-27">&#182;</a>
              </div>
              <h1>AT RULE</h1>

            </div>
            
        </li>
        
        
        <li id="section-28">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-28">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    atrule: <span class="keyword">function</span>(){
        <span class="keyword">var</span> lv = <span class="keyword">this</span>.ll().val.toLowerCase();    
        <span class="keyword">var</span> node;
        <span class="keyword">if</span>(<span class="keyword">this</span>[lv]){
            node = <span class="keyword">this</span>[lv]()
            <span class="keyword">return</span> node;
        };
        <span class="keyword">return</span> <span class="keyword">this</span>.unkownAtRule();
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-29">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-29">&#182;</a>
              </div>
              <p>type: 
 0 - defaults atkeyword start
 1 - $dollarIdent start</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="keyword">var</span>: <span class="keyword">function</span>(type){
        <span class="keyword">if</span>(!type){
            <span class="keyword">this</span>.next();
            <span class="keyword">this</span>.match(<span class="string">'WS'</span>);
        }
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.Variable(), 
            la, ll=<span class="keyword">this</span>.ll();
        <span class="keyword">this</span>.match(<span class="string">'IDENT'</span>);
        <span class="keyword">this</span>.match(<span class="string">'WS'</span>);</pre></div></div>
            
        </li>
        
        
        <li id="section-30">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-30">&#182;</a>
              </div>
              <p>this.markstack;
debugger
this.next(3);
var haha = this.ll()</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        node.name = ll.val;
        node.value = <span class="keyword">this</span>.componentValues();
        <span class="keyword">this</span>.matcheNewLineOrSemeColon();
        <span class="keyword">this</span>.scope.define(node.name, node);
        <span class="keyword">return</span> node;
    },
    css: <span class="keyword">function</span>(){

    },</pre></div></div>
            
        </li>
        
        
        <li id="section-31">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-31">&#182;</a>
              </div>
              <p>type: 
 0 - defaults atkeyword start
 1 - .className start</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    mixin: <span class="keyword">function</span>(){
        <span class="keyword">this</span>.match(<span class="string">'AT_KEYWORD'</span>);
        <span class="keyword">this</span>.match(<span class="string">'WS'</span>);
        <span class="keyword">var</span> name = <span class="keyword">this</span>.ll().val;
        <span class="keyword">this</span>.match(<span class="string">'FUNCTION'</span>);
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.Mixin(name);
        <span class="keyword">this</span>.eat(<span class="string">'WS'</span>);
        node.formalParams = []; 
        <span class="keyword">if</span>(<span class="keyword">this</span>.eat(<span class="string">'('</span>)){
            <span class="keyword">this</span>.skipWSorNewlne();
            <span class="keyword">if</span>(<span class="keyword">this</span>.la() !== <span class="string">')'</span>){
                <span class="keyword">do</span>{
                    node.formalParams.push(<span class="keyword">this</span>.param());
                    <span class="keyword">this</span>.skipWSorNewlne();
                }<span class="keyword">while</span>(<span class="keyword">this</span>.eat(<span class="string">','</span>))
            }
        }
        <span class="keyword">this</span>.match(<span class="string">')'</span>);
        <span class="keyword">this</span>.skipWSorNewlne();
        <span class="keyword">this</span>.down();

        node.scope = <span class="keyword">this</span>.scope;
        node.block = <span class="keyword">this</span>.block();
        
        <span class="keyword">this</span>.up();
        <span class="keyword">this</span>.scope.define(node.name, node);
        <span class="keyword">return</span> node;
    },
    param: <span class="keyword">function</span>(){
        <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll();
        <span class="keyword">this</span>.match(<span class="string">'IDENT'</span>);
        <span class="keyword">return</span> <span class="keyword">new</span> tree.Param(ll.val);
    },
    extend: <span class="keyword">function</span>(){
        <span class="keyword">this</span>.match(<span class="string">'AT_KEYWORD'</span>);
        <span class="keyword">this</span>.match(<span class="string">'WS'</span>);
        <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll();
        <span class="keyword">var</span> la = ll.type;
        <span class="keyword">var</span> node;
        <span class="keyword">if</span>(la === <span class="string">'IDENT'</span> || la === <span class="string">'CLASS'</span>){
            <span class="keyword">var</span> mixin = <span class="keyword">this</span>.scope.resolve(ll.val);
            <span class="keyword">if</span>(!mixin) {
                <span class="keyword">this</span>.error(<span class="string">'undefined mixin -&gt; '</span> + ll.val);
            }
            <span class="keyword">if</span>(mixin.refs === <span class="literal">undefined</span>){
                <span class="keyword">this</span>.error(<span class="string">'not a expected type mixin -&gt; '</span> + ll.val); 
            }<span class="keyword">else</span>{
                <span class="keyword">this</span>.next();
                node = <span class="keyword">new</span> tree.Extend();
                node.mixin = mixin;
                <span class="keyword">this</span>.matcheNewLineOrSemeColon();
                <span class="keyword">return</span> node;
            }
        }
        <span class="keyword">this</span>.error(<span class="string">'invalid extend at rule'</span>);
    },
    include: <span class="keyword">function</span>(){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.Include();
        <span class="keyword">this</span>.match(<span class="string">'AT_KEYWORD'</span>);
        <span class="keyword">this</span>.match(<span class="string">'WS'</span>);
        node.name = <span class="keyword">this</span>.ll().val;
        <span class="keyword">this</span>.match(<span class="string">'FUNCTION'</span>);
        <span class="keyword">if</span>(<span class="keyword">this</span>.eat(<span class="string">'('</span>)){
            <span class="keyword">this</span>.skipWSorNewlne();
            <span class="keyword">if</span>(<span class="keyword">this</span>.la() !== <span class="string">')'</span>){
                <span class="keyword">do</span>{
                    node.params.push(<span class="keyword">this</span>.componentValues(isCommaOrParen));
                    <span class="keyword">if</span>(<span class="keyword">this</span>.la() === <span class="string">')'</span>) <span class="keyword">break</span>;
                }<span class="keyword">while</span>(<span class="keyword">this</span>.eat(<span class="string">','</span>))
            }
            <span class="keyword">this</span>.match(<span class="string">')'</span>);
        }
        <span class="keyword">this</span>.matcheNewLineOrSemeColon();
        node.scope = <span class="keyword">this</span>.scope;
        <span class="keyword">return</span>  node;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-32">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-32">&#182;</a>
              </div>
              <p>@import xx mediaquery_list;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    import: <span class="keyword">function</span>(){

    },</pre></div></div>
            
        </li>
        
        
        <li id="section-33">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-33">&#182;</a>
              </div>
              <pre><code> media</code></pre>
<p>==================</p>

            </div>
            
        </li>
        
        
        <li id="section-34">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-34">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    media: <span class="keyword">function</span>(){

    },
    media_query_list: <span class="keyword">function</span>(){

    },
    media_query: <span class="keyword">function</span>(){

    },



    <span class="string">"font-face"</span>: <span class="keyword">function</span>(){

    },
    charset: <span class="keyword">function</span>(){

    },
    keyframe: <span class="keyword">function</span>(){

    },
    page: <span class="keyword">function</span>(){

    },</pre></div></div>
            
        </li>
        
        
        <li id="section-35">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-35">&#182;</a>
              </div>
              <p>所有未定义rule</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    unknownAtRule: <span class="keyword">function</span>(){

    },</pre></div></div>
            
        </li>
        
        
        <li id="section-36">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-36">&#182;</a>
              </div>
              <p>ruleset
 :  selectorlist &#39;{&#39; rule ((NewLine|;) rule)* &#39;}&#39;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    ruleset: <span class="keyword">function</span>(){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.RuleSet(),
            rule;</pre></div></div>
            
        </li>
        
        
        <li id="section-37">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-37">&#182;</a>
              </div>
              <ol>
<li>是Selector Sep 2 </li>
<li>在是IDENT(Selector Sep之一)时后续不接: 代表不是declaration //  &amp;&amp;(la !== &#39;IDENT&#39;|| this.la(2) !== &#39;:&#39;
@changelog: 2 remove 这不需要</li>
</ol>

            </div>
            
            <div class="content"><div class='highlight'><pre>        node.selector = <span class="keyword">this</span>.concatSelector(<span class="keyword">this</span>.selectorList());
        <span class="keyword">this</span>.skipWSorNewlne();
        <span class="keyword">this</span>.down(node);
        node.block = <span class="keyword">this</span>.block();
        <span class="keyword">this</span>.up(node);
        <span class="keyword">return</span> node;
    },
    block: <span class="keyword">function</span>(){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.Block();
        <span class="keyword">this</span>.match(<span class="string">'{'</span>);
        <span class="keyword">this</span>.skipStart();
        <span class="keyword">while</span>(<span class="keyword">this</span>.la() !== <span class="string">'}'</span>){
            <span class="keyword">this</span>.skipStart();</pre></div></div>
            
        </li>
        
        
        <li id="section-38">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-38">&#182;</a>
              </div>
              <p>*height: 80px;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            <span class="keyword">if</span>(<span class="keyword">this</span>.ll(<span class="number">1</span>).type == <span class="string">'*'</span> &amp;&amp; <span class="keyword">this</span>.ll(<span class="number">2</span>).type == <span class="string">'IDENT'</span>){
                <span class="keyword">this</span>.ll(<span class="number">2</span>).val = <span class="string">"*"</span> + <span class="keyword">this</span>.ll(<span class="number">2</span>).val;
                <span class="keyword">this</span>.next();
            }
            <span class="keyword">var</span> ll1 = <span class="keyword">this</span>.ll(<span class="number">1</span>);
            <span class="keyword">var</span> ll2 = <span class="keyword">this</span>.ll(<span class="number">2</span>);</pre></div></div>
            
        </li>
        
        
        <li id="section-39">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-39">&#182;</a>
              </div>
              <p>height</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            <span class="keyword">if</span>(ll1.type === <span class="string">'IDENT'</span> &amp;&amp;</pre></div></div>
            
        </li>
        
        
        <li id="section-40">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-40">&#182;</a>
              </div>
              <p>float:left  即精贴着导致tokenizer为pesudo class
@TODO: fix</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                (ll2.type === <span class="string">':'</span> || ll2.type == <span class="string">'PSEUDO_CLASS'</span> <span class="comment">/*&amp;&amp; mayNotPsedudoClass.test(ll2.val)*/</span>)){
                <span class="keyword">try</span>{
                    <span class="keyword">this</span>.mark();
                    <span class="keyword">var</span> declaration = <span class="keyword">this</span>.declaration();
                    node.list.push(declaration);</pre></div></div>
            
        </li>
        
        
        <li id="section-41">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-41">&#182;</a>
              </div>
              <p>说明declar不成</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                }<span class="keyword">catch</span>(_e){
                    <span class="keyword">if</span>(_e.code === <span class="number">1987</span>){
                        <span class="keyword">this</span>.restore();
                        node.list.push(<span class="keyword">this</span>.stmt());
                    }<span class="keyword">else</span>{
                        <span class="keyword">throw</span> _e;
                    }
                }

            }<span class="keyword">else</span>{</pre></div></div>
            
        </li>
        
        
        <li id="section-42">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-42">&#182;</a>
              </div>
              <p>console.log(this.ll(), this.ll(2), this.ll(3))</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                node.list.push(<span class="keyword">this</span>.stmt());
            }
            <span class="keyword">this</span>.skipStart();
        }
        <span class="keyword">this</span>.match(<span class="string">'}'</span>);
        <span class="keyword">return</span> node;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-43">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-43">&#182;</a>
              </div>
              <p>selectorList
 : complexSelector (, complexSelector)*
 ;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    selectorList: <span class="keyword">function</span>(){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.SelectorList();
        node.list.push(<span class="keyword">this</span>.complexSelector());
        <span class="keyword">this</span>.skipWSorNewlne();
        <span class="keyword">while</span>(<span class="keyword">this</span>.la() === <span class="string">','</span>){
            <span class="keyword">this</span>.next();
            <span class="keyword">this</span>.skipWSorNewlne();
            node.list.push(<span class="keyword">this</span>.complexSelector()); 
            <span class="keyword">this</span>.skipWSorNewlne();
        }
        <span class="keyword">return</span> node;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-44">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-44">&#182;</a>
              </div>
              <p>由于只是要翻译，略过更基础的的不做记录  只需处理SelectorList</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    complexSelector: <span class="keyword">function</span>(){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.ComplexSelector();
        <span class="keyword">var</span> selectorString = <span class="string">''</span>;
        <span class="keyword">while</span>(<span class="literal">true</span>){
            <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll();
            <span class="keyword">if</span>(isSelectorSep(ll.type)){
                selectorString += ll.val || (ll.type === <span class="string">'WS'</span> ? <span class="string">' '</span> : ll.type );
                <span class="keyword">this</span>.next();
            }<span class="keyword">else</span>{
                <span class="keyword">break</span>;
            }
        }
        node.string = selectorString; 
        <span class="keyword">return</span> node;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-45">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-45">&#182;</a>
              </div>
              <p>rule
 : declaration
 | stmt
 | skipped;    &#39;; NEWLINE COMMENT SPACE&#39;
 ;</p>
<p>compoundSelector: function(){</p>
<p>},
simpleSelector: function(){</p>
<p>},</p>
<p>declaration
 : 
 | IDENT : Value  // start with $
 ; </p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    declaration: <span class="keyword">function</span>(checked){
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.Declaration(),
            ll1 = <span class="keyword">this</span>.ll(<span class="number">1</span>),
            ll2 = <span class="keyword">this</span>.ll(<span class="number">2</span>);
        node.property = ll1.val;</pre></div></div>
            
        </li>
        
        
        <li id="section-46">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-46">&#182;</a>
              </div>
              <p>说明是PSEUDO_CLASS</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">this</span>.next(<span class="number">2</span>);
        node.value = <span class="keyword">this</span>.componentValues();
        <span class="keyword">this</span>.matcheNewLineOrSemeColon();
        <span class="keyword">if</span>(ll2.type !== <span class="string">':'</span>) node.value.list.unshift({
            type: <span class="string">'IDENT'</span>,
            val: ll2.val.slice(<span class="number">1</span>)
        })
        <span class="keyword">return</span> node;
    },
    componentValues: <span class="keyword">function</span>(end){
        <span class="keyword">if</span>(end){
            <span class="keyword">var</span> test = <span class="keyword">typeof</span> end === <span class="string">'string'</span>? <span class="keyword">function</span>(type){type === end} : end;
        }
        <span class="keyword">var</span> node = <span class="keyword">new</span> tree.ComponentValues(),
            ll, la, i = <span class="number">10</span>;
        <span class="keyword">while</span>(i++){
            ll = <span class="keyword">this</span>.ll(<span class="number">1</span>);
            la = ll.type;
            <span class="keyword">if</span>(i &gt; <span class="number">100</span>) <span class="keyword">throw</span> Error(<span class="string">'dada'</span>); 
            <span class="keyword">if</span>(la === <span class="string">'IMPORTANT'</span>){
                <span class="keyword">this</span>.next();
                node.important = <span class="literal">true</span>;
                <span class="keyword">this</span>.matcheNewLineOrSemeColon();
                <span class="keyword">break</span>;
            }
            <span class="keyword">if</span>((test &amp;&amp; test(la)) || (la === <span class="string">'NEWLINE'</span> || la === <span class="string">';'</span>)){</pre></div></div>
            
        </li>
        
        
        <li id="section-47">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-47">&#182;</a>
              </div>
              <p>this.next();</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                <span class="keyword">break</span>;
            }<span class="keyword">else</span>{
                <span class="keyword">var</span> componentValue = <span class="keyword">this</span>.componentValue()
                <span class="keyword">if</span>(componentValue <span class="keyword">instanceof</span> tree.ComponentValues){
                    node.list = node.list.concat(componentValue.list);

                }<span class="keyword">else</span> <span class="keyword">if</span>(componentValue !== <span class="literal">null</span>) node.list.push(componentValue);
            }
        }
        <span class="keyword">return</span> node;

    },</pre></div></div>
            
        </li>
        
        
        <li id="section-48">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-48">&#182;</a>
              </div>
              <p>css syntax  value</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    componentValue: <span class="keyword">function</span>(){
        <span class="keyword">var</span> ll1 = <span class="keyword">this</span>.ll(<span class="number">1</span>);
        <span class="keyword">var</span> node, val = ll1.val, res;</pre></div></div>
            
        </li>
        
        
        <li id="section-49">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-49">&#182;</a>
              </div>
              <p>如果是计算表达式 @TODO: 加入颜色运算</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">switch</span>(ll1.type){
            <span class="keyword">case</span> <span class="string">'{'</span>:</pre></div></div>
            
        </li>
        
        
        <li id="section-50">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-50">&#182;</a>
              </div>
              <p>case &#39;&gt;&#39;:
case &#39;+&#39;:
@FIX   暂时这样处理declaration 与ruleset的冲突
code 1987代表返回mark处
throw 的代价远比创建小</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                perror.code = <span class="number">1987</span>;
                <span class="keyword">throw</span> perror;
                <span class="keyword">break</span>;
            <span class="keyword">case</span> <span class="string">','</span>:
            <span class="keyword">case</span> <span class="string">'='</span>:
                <span class="keyword">this</span>.next();
                <span class="keyword">return</span> ll1;
            <span class="keyword">case</span> <span class="string">'WS'</span>:
                <span class="keyword">this</span>.next();
                <span class="keyword">return</span> <span class="literal">null</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-51">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-51">&#182;</a>
              </div>
              <p>case &#39;IDENT&#39;:
    this.next();
    var ref = this.scope.resolve(ll1.val);
    if(ref &amp;&amp; ref.kind === &#39;var&#39;){
        return ref;
    }else{
        return ll1;
    }
case &#39;WS&#39;:
    this.next();
    return null;
case &#39;RGBA&#39;:
case &#39;STRING&#39;:
case &#39;,&#39;:
case &#39;URI&#39;: 
    this.next();
    return ll1;
case &#39;FUNCTION&#39;:
    this.match(&#39;(&#39;);
    var params = [];
    var fn = ll1.val;
    while(this.la() != &#39;)&#39;){
        node.params.push(this.expression());
    }
    this.match(&#39;)&#39;);
    return node;</p>
<p>case &#39;DIMENSION&#39;:
case &#39;(&#39;:
    // this.match(&#39;(&#39;);
    var node = this.additive();
    // this.match(&#39;)&#39;);
    return node;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            <span class="keyword">default</span>: 
                <span class="keyword">return</span> <span class="keyword">this</span>.expression();
        }
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-52">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-52">&#182;</a>
              </div>
              <p>componentValue 
 : 
IDENT                // tokenNode
HASH                 // 进行 rgba的侦测 计算computed
STRING               // 暂时TokenType
URL                  //
DELIM  |? @remove
NUMBER               // 合并成计算 computed
PERCENTAGE<br>DIMENSION         </p>
<p>WHITESPACE           // tokenNode
Function block       // mcss BuildInFunction 计算 或者tokenNode
COMMA  ,             // tokenNode
() block<br>AT-KEYWORD
CDO @remove
CDC @remove
COLON  : @remove
SEMICOLON     ; @remove
{} block<br>[] block  @remove</p>
<p>expression
 : multive + addtive
 : expression</p>
<p>@todo 目前 exression 与componentValue 重复 与 addtive重复</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    expression: <span class="keyword">function</span>(prefix){
        <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll(<span class="number">1</span>),
            la = ll.type, node;

        <span class="keyword">switch</span>(ll.type){
            <span class="keyword">case</span> <span class="string">'('</span>:
                node = <span class="keyword">this</span>.parenExpression();
                <span class="keyword">break</span>;
            <span class="keyword">case</span> <span class="string">'DIMENSION'</span>:
                node = <span class="keyword">this</span>.additive();
                <span class="keyword">break</span>;
            <span class="keyword">case</span> <span class="string">'+'</span>:
            <span class="keyword">case</span> <span class="string">'-'</span>:
                <span class="keyword">if</span>(<span class="keyword">this</span>.ll(<span class="number">2</span>)!==<span class="string">'ws'</span>){
                    node = <span class="keyword">this</span>.expression(ll.type)
                }<span class="keyword">else</span>{
                    node = ll;
                }
            <span class="keyword">case</span> <span class="string">'WS'</span>:
            <span class="keyword">case</span> <span class="string">'NEWLINE'</span>:
                <span class="keyword">this</span>.next();
                node = <span class="keyword">this</span>.expression();
                <span class="keyword">break</span>;
            <span class="keyword">case</span> <span class="string">'IDENT'</span>:
            <span class="keyword">case</span> <span class="string">'STRING'</span>:
            <span class="keyword">case</span> <span class="string">'RGBA'</span>:
            <span class="keyword">case</span> <span class="string">'URI'</span>:
                <span class="keyword">this</span>.next();
                node = ll;
                <span class="keyword">break</span>;
            <span class="keyword">case</span> <span class="string">'HASH'</span>:
                <span class="keyword">this</span>.next();
                val = ll.val;
                <span class="keyword">if</span>(<span class="regexp">/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/</span>.test(val)){
                    node = <span class="keyword">new</span> tree.RGBA(<span class="keyword">new</span> Color(val));
                }<span class="keyword">else</span>{
                    node = <span class="keyword">new</span> tree.Unknown(ll.val);
                }
                <span class="keyword">break</span>;
            <span class="keyword">case</span> <span class="string">'FUNCTION'</span>:
                <span class="keyword">this</span>.next();
                <span class="keyword">this</span>.match(<span class="string">'('</span>);
                <span class="keyword">var</span> fn = functions[ll.val];
                <span class="keyword">if</span>(!fn){</pre></div></div>
            
        </li>
        
        
        <li id="section-53">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-53">&#182;</a>
              </div>
              <p>then means css function</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                    node = <span class="keyword">new</span> tree.CssFunction(ll.val);
                    node.value = <span class="keyword">this</span>.componentValues(<span class="string">')'</span>);
                    <span class="keyword">this</span>.match(<span class="string">')'</span>)
                }<span class="keyword">else</span>{
                    <span class="keyword">var</span> params = [];
                    <span class="keyword">this</span>.skipWSorNewlne();
                    <span class="keyword">if</span>(<span class="keyword">this</span>.la() !== <span class="string">')'</span>){
                        <span class="keyword">do</span>{
                            params.push(<span class="keyword">this</span>.expression());
                        }<span class="keyword">while</span>(<span class="keyword">this</span>.la() === <span class="string">','</span>)
                    }
                    <span class="keyword">this</span>.match(<span class="string">')'</span>);
                    node = fn.apply(<span class="keyword">this</span>, params);</pre></div></div>
            
        </li>
        
        
        <li id="section-54">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-54">&#182;</a>
              </div>
              <p>所有函数如果返回了字符串 都认为是要原样输出，否则应返回node 参与计算</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                    <span class="keyword">if</span>(<span class="keyword">typeof</span> node === <span class="string">'string'</span>){
                        node = <span class="keyword">new</span> tree.Unknown(node);
                    }
                }
                <span class="keyword">break</span>; 
            <span class="keyword">default</span>:
                <span class="keyword">this</span>.error(<span class="string">'invalid expression start:'</span>+ ll.type);

        }
        <span class="keyword">if</span>(node &amp;&amp; node.type === <span class="string">'DIMENSION'</span>){
            <span class="keyword">if</span>(prefix === <span class="string">'-'</span>){
                node.val.number = <span class="number">0</span> - node.val.number;
            }
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-55">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-55">&#182;</a>
              </div>
              <p>console.log(node)</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="keyword">return</span> node;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-56">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-56">&#182;</a>
              </div>
              <h2>simple caculator</h2>

            </div>
            
        </li>
        
        
        <li id="section-57">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-57">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    additive: <span class="keyword">function</span>(options){
        <span class="keyword">var</span> left = <span class="keyword">this</span>.multive(), right;
        <span class="keyword">this</span>.eat(<span class="string">'WS'</span>);
        <span class="keyword">var</span> op = <span class="keyword">this</span>.ll();
        <span class="keyword">if</span>(op.type === <span class="string">'+'</span> || op.type === <span class="string">'-'</span>){
            <span class="keyword">this</span>.next();
            <span class="keyword">this</span>.eat(<span class="string">'WS'</span>);
            right = <span class="keyword">this</span>.additive();
            <span class="keyword">return</span> <span class="keyword">this</span>._add(left, right, op.type);
        }<span class="keyword">else</span>{
            <span class="keyword">return</span> left;
        }
    },
    multive: <span class="keyword">function</span>(){
        <span class="keyword">var</span> left = <span class="keyword">this</span>.primary(), right;
        <span class="keyword">var</span> op = <span class="keyword">this</span>.ll();
        <span class="keyword">if</span>(op.type === <span class="string">'*'</span> || op.type === <span class="string">'/'</span>){
            <span class="keyword">this</span>.next();
            right = <span class="keyword">this</span>.multive();
            <span class="keyword">return</span> <span class="keyword">this</span>._mult(left, right, op.type);
        }<span class="keyword">else</span>{
            <span class="keyword">return</span> left;
        }
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-58">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-58">&#182;</a>
              </div>
              <p>dimension + dimension
dimension - dimension
单位永远以第一个为准</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    _add: <span class="keyword">function</span>(d1, d2, op){
        <span class="keyword">var</span> val1 = d1.val, 
            val2 = d2.val,
            unit, number;

        <span class="keyword">if</span>(val1.unit){
            unit = val1.unit;
        }<span class="keyword">else</span>{
            unit = val2.unit;
        }
        <span class="keyword">if</span>(op === <span class="string">'+'</span>){ <span class="comment">//+</span>
            number = val1.number + val2.number;
        }<span class="keyword">else</span>{ <span class="comment">//-</span>
            number = val1.number - val2.number;
        }
        <span class="keyword">return</span> {
            type: <span class="string">'DIMENSION'</span>,
            val: {
                number: number,
                unit: unit
            }
        }

    },</pre></div></div>
            
        </li>
        
        
        <li id="section-59">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-59">&#182;</a>
              </div>
              <p>dimension * dimension
dimension / dimension</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    _mult: <span class="keyword">function</span>(d1, d2, op){
        <span class="keyword">var</span> val1 = d1.val, 
            val2 = d2.val,
            unit, number;

        <span class="keyword">if</span>(val1.unit){
            unit = val1.unit;
        }<span class="keyword">else</span>{
            unit = val2.unit;
        }

        <span class="keyword">if</span>(op === <span class="string">'*'</span>){ <span class="comment">//+</span>
            number = val1.number * val2.number;
        }<span class="keyword">else</span>{ <span class="comment">//-</span>
            <span class="keyword">if</span>(val2.number === <span class="number">0</span>) <span class="keyword">this</span>.error(<span class="string">'can"t divid by zero'</span>);
            number = val1.number / val2.number;
        }
        <span class="keyword">return</span> {
            type: <span class="string">'DIMENSION'</span>,
            val: {
                number: number,
                unit: unit
            }
        }
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-60">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-60">&#182;</a>
              </div>
              <p>(additive)
dimension</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    primary: <span class="keyword">function</span>(){
        <span class="keyword">var</span> ll = <span class="keyword">this</span>.ll();
        <span class="keyword">if</span>(ll.type === <span class="string">'DIMENSION'</span>){
            <span class="keyword">this</span>.next();
            <span class="keyword">return</span> ll;
        } 
        <span class="keyword">if</span>(ll.type === <span class="string">'('</span>){
            <span class="keyword">this</span>.next();
            <span class="keyword">var</span> d1 = <span class="keyword">this</span>.additive();
            <span class="keyword">this</span>.match(<span class="string">')'</span>)
            <span class="keyword">return</span> d1;
        }
        <span class="keyword">this</span>.error(<span class="string">'invalid primary'</span>);
    },

    parenExpression:<span class="keyword">function</span>(){
        <span class="keyword">this</span>.match(<span class="string">'('</span>);
        <span class="keyword">var</span> t = <span class="keyword">this</span>.expression();
        <span class="keyword">this</span>.match(<span class="string">')'</span>);
        <span class="keyword">return</span> t;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-61">
            <div class="annotation">
              
              <div class="pilwrap for-h1">
                <a class="pilcrow" href="#section-61">&#182;</a>
              </div>
              <h1>private function</h1>

            </div>
            
        </li>
        
        
        <li id="section-62">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-62">&#182;</a>
              </div>
              <p>inspect lookahead array</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    _lookahead: <span class="keyword">function</span>(){
        <span class="keyword">return</span> <span class="keyword">this</span>.lookahead.map(<span class="keyword">function</span>(item){
            <span class="keyword">return</span> item.type
        }).join(<span class="string">','</span>)
    }




}</pre></div></div>
            
        </li>
        
        
        <li id="section-63">
            <div class="annotation">
              
              <div class="pilwrap for-h2">
                <a class="pilcrow" href="#section-63">&#182;</a>
              </div>
              <h2>1. grammer</h2>

            </div>
            
        </li>
        
        
        <li id="section-64">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-64">&#182;</a>
              </div>
              <p>stylesheet
  :  stmt EOF 
  ;</p>
<p>stmt
  :  ruleset
  |  directive
  |  atrule
  ;</p>
<p>directive
  :  var_directive
  :  if_directive
  |  for_directive</p>
<p>expression
  :  literal
  |  </p>
<p>literal
  :  arrayLiteral
  |  </p>
<p>ruleset
  :  assign
  |  rule
  ;  </p>
<p>atrule
  : import
  | charset 
  | font-face
  | page
  | KEYFRAME keyframe_block
  ;</p>
<p>keyframe
  : KEYFRAME keyframe_block
  ;</p>
<p>keyframe_blocks</p>
<p>import
  : IMPORT URL media_query_list?      :@import url(&#39;xx.js&#39;) screen 
  | IMPORT STRING media_query_list?      :@import url(&#39;xx.js&#39;) screen 
  ;</p>
<p>charset
  : CHARSET STRING
  ;</p>
<p>page
  : PAGE</p>
<p>--------------------暂时不这么细-----------------
media
  : MEDIA media_query_list;
  | </p>
<p>media_query_list
  : media_query_list , media_query;
  | </p>
<p>media_query
  : media_query_prefixer</p>
<p>media_query_prefixer
  : media_query_prefixer</p>
<p>media_query_keyword
  : </p>
<p>media_query_expression</p>
<h2>  : </h2>

            </div>
            
        </li>
        
        
        <li id="section-65">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-65">&#182;</a>
              </div>
              <p>rule
  : SELECTOR block
  | KEYFRAME block
  | MEDIA block
  ;</p>
<p>block
  : asign
  | mixin
  | </p>
<p>mixin
  : MIXIN VARIABLE &#39;(&#39; paramlist? &#39;)&#39;
  | MIXIN VARIABLE
  ;</p>
<p>assign
  : VARIABLE COLON(:) EXPRESSION</p>
<p>parenBlock
    : stmt
    ;</p>

            </div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
